namespace Webbness.Generator.CodeDom

import System
import System.Collections
import System.IO
import Neo.Generator.CodeGen
import Neo.MetaModel.Reader
import Neo.Generator.Core
import Neo.MetaModel

class ValidModelFactory:
	
	_validatingModel as ValidatingModel
	
	def constructor():
		_validatingModel = ValidatingModel()
		_validatingModel.IsValid = true
	
	def Create(pathToXmlFile as string) as ValidatingModel:
		using xtr = System.Xml.XmlTextReader(pathToXmlFile):
			xtr.XmlResolver = LocalDocumentTypeResolver(Path.Combine(Path.GetDirectoryName(pathToXmlFile), 'norque.dtd'))
			using reader = System.Xml.XmlValidatingReader(xtr):
				reader.ValidationType = System.Xml.ValidationType.DTD
				reader.ValidationEventHandler += reader_ValidationEventHandler
				//perform dtd validation
				while reader.Read():
					pass
		if not _validatingModel.IsValid:
			return _validatingModel
		
		modelReader = NorqueReader()
		modelReader.ReadConfiguration(pathToXmlFile, ConfigDelegate(setPiAttribute))
		modelReader.LoadModel(pathToXmlFile)
		
		for entity as Entity in modelReader.Model.Entities:
			if entity.ForceOverwrite:
				_validatingModel.HasForcedOverwrite = true
				_validatingModel.Message.AppendLine(entity.ClassName)
			
#			if entity.IdMethod == Neo.MetaModel.IdMethod.IdBroker or entity.IdMethod == Neo.MetaModel.IdMethod.None:
#				_validatingModel.Message.AppendLine("Webbness only supports 'Native' and 'Guid' ID Methods.")
#				_validatingModel.IsValidModel = false
			if entity.PkColumns.Count == 0:
				_validatingModel.Message.AppendFormat('The table \'{0}\' does not contain a primary key.', entity.TableName).AppendLine()
				_validatingModel.IsValid = false
			attList = ArrayList()
			for attribute as EntityAttribute in entity.Attributes:
				if attList.Contains(attribute.DotNetName):
					_validatingModel.Message.AppendFormat('The class \'{0}\' contains a duplicate property name {1}.', entity.ClassName, attribute.DotNetName).AppendLine()
					_validatingModel.IsValid = false
				else:
					attList.Add(attribute.DotNetName)
			for relation as EntityRelationship in entity.Relationships:
				if attList.Contains(relation.DotNetName):
					_validatingModel.Message.AppendFormat('The class \'{0}\' contains a duplicate property name {1}.', entity.ClassName, relation.DotNetName).AppendLine()
					_validatingModel.IsValid = false
				else:
					attList.Add(relation.DotNetName)
		if _validatingModel.IsValid:
			_validatingModel.Model = modelReader.Model
		return _validatingModel
	
	private def reader_ValidationEventHandler(sender as object, e as System.Xml.Schema.ValidationEventArgs):
		_validatingModel.Message.AppendLine('Validation Error')
		_validatingModel.Message.AppendLine(e.Exception.Message)
		_validatingModel.Message.AppendFormat('At line {0}', e.Exception.LineNumber)
		_validatingModel.Message.AppendFormat('At position {0}', e.Exception.LinePosition)
		_validatingModel.IsValid = false
	
	private def setPiAttribute(filename as string, attr as string, val as string):
		if attr.Equals("path", StringComparison.InvariantCultureIgnoreCase):
			_validatingModel.ResourcePath = Path.Combine(Path.GetDirectoryName(filename), val)
		elif attr.Equals("user", StringComparison.InvariantCultureIgnoreCase):
			_validatingModel.UserClassTemplate = val
		elif attr.Equals("userfileextension", StringComparison.InvariantCultureIgnoreCase):
			_validatingModel.UserFileExtension = val
		elif attr.Equals("support", StringComparison.InvariantCultureIgnoreCase):
			_validatingModel.SupportClassesTemplate = val
		elif attr.Equals("supportfileextension", StringComparison.InvariantCultureIgnoreCase):
			_validatingModel.SupportFileExtension = val
		else:
			_validatingModel.Properties[attr] = val
